Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.

...powered by www.netzwerkartist.de...

 << zurück
Visual C# 2005 von Andreas Kühnel
Das umfassende Handbuch
Buch: Visual C# 2005

Visual C# 2005
1.320 S., mit 2 CDs, 59,90 Euro
Galileo Computing
ISBN 3-89842-586-X
gp Kapitel 23 Das Drucken (Printing)
  gp 23.1 Ein einführender Überblick
  gp 23.2 Einen Druckauftrag erteilen
    gp 23.2.1 Methoden und Eigenschaften von »PrintDocument«
    gp 23.2.2 Die Ereignisse eines »PrintDocument«-Objekts
    gp 23.2.3 Die Ereignisse »BeginPrint« und »EndPrint«
    gp 23.2.4 Das Ereignis »QueryPageSettings«
    gp 23.2.5 Das Ereignis »PrintPage«
    gp 23.2.6 Das Beenden des Druckauftrags
    gp 23.2.7 Programmbeispiel
  gp 23.3 Seiteneinstellungen mit »PageSettings«
  gp 23.4 Der Drucker als »PrinterSettings«-Objekt
    gp 23.4.1 Mehrere installierte Drucker
    gp 23.4.2 Wichtige Eigenschaften des »PrinterSettings«-Objekts
  gp 23.5 Die Steuerelemente zum Drucken
    gp 23.5.1 Das »PrintDocument«-Steuerelement
    gp 23.5.2 Das »PrintDialog«-Steuerelement
    gp 23.5.3 Das »PageSetupDialog«-Steuerelement
    gp 23.5.4 Das »PrintPreviewDialog«-Steuerelement
    gp 23.5.5 Das »PrintPreviewControl«-Steuerelement
  gp 23.6 Drucken von Grafiken
    gp 23.6.1 Festlegung der Einheiten und Skalierung
    gp 23.6.2 Beispielprogramm zum Drucken einer Grafik
  gp 23.7 Ausdruck von mehrseitigem Text


Galileo Computing

23.7 Ausdruck von mehrseitigem Textoptop

Zum Abschluss der Thematik des Druckens folgt nun noch ein Beispielprogramm, dass den Inhalt einer Textbox formatiert ausgibt und außerdem berücksichtigt, dass der Ausdruck unter Umständen mehrere Druckseiten lang ist.

Dazu stelle ich Ihnen das Programm, das auf den hochtrabenden Namen Texteditor lautet, vor. Ein wenig überzogen ist der Name aus dem Grund, weil im Wesentlichen nur die mit dem Drucken eines Dokuments zusammenhängenden Möglichkeiten üblicher Texteditoren implementiert sind. Es ist allerdings nicht sonderlich schwierig, das Programm zu ergänzen – beispielsweise um das Menü Bearbeiten mit den Auswahlmöglichkeiten Kopieren, Ausschneiden und Einfügen.

Sehen wir uns nun den Programmcode zusammengefasst an – allerdings zunächst nur die Passagen, die keiner genaueren Erklärung bedürfen. Dazu gehört jedoch nicht der Ereignishandler des PrintPage-Ereignisses, den wir anschließend Zeile für Zeile behandeln werden.


// --------------------------------------------------------------
// Beispiel: ...\Kapitel 23\Texteditor
// --------------------------------------------------------------
...
public partial class Form1 : Form {
  ...
  // Startseite zum Drucken
  private int startSeite;
  // Anzahl der Druckseiten
  private int anzahlSeiten;
  // aktuelle Seitenzahl
  private int seitenNummer;
  // zu druckender Text
  private string strPrintText;
  // der Name der geöffneten Datei
  private string strDateiName;
  private void mnuDrucken_Click(object sender, EventArgs e) {
    printDialog1.AllowSomePages = true;
    if (printDialog1.ShowDialog() == DialogResult.OK) {
      printDocument1.DocumentName = "Dokument";
      // Startwerte abhängig vom zu druckenden 
      // Text initialisieren
      switch (printDialog1.PrinterSettings.PrintRange) {
        case PrintRange.AllPages:
          strPrintText = textBox1.Text;
          startSeite = 1;
          anzahlSeiten = printDialog1.PrinterSettings.MaximumPage;
          break;
        case PrintRange.SomePages:
          strPrintText = textBox1.Text;
          startSeite = printDialog1.PrinterSettings.FromPage;
          anzahlSeiten = printDialog1.PrinterSettings.ToPage
                                             – startSeite + 1;
          break;
      }
      // Drucken starten
      seitenNummer = 1;
      printDocument1.Print();
    }
  }
  // das Menü 'Öffnen'
  private void mnuOpen_Click(object sender, EventArgs e) {
    openFileDialog1.Filter = "Text Documents(*.txt) " +
                               " |*.txt|All Files(*.*)|*.*"; 
    openFileDialog1.FileName = "*.txt";
    StreamReader sr;
    if (openFileDialog1.ShowDialog() == DialogResult.OK)
      try {
        this.strDateiName = openFileDialog1.FileName;
        sr = new StreamReader(this.strDateiName);
        textBox1.Text = sr.ReadToEnd();
        sr.Close();
      }
      catch (Exception exc) {
        MessageBox.Show(exc.Message, "Texteditor",
                           MessageBoxButtons.OK,
                           MessageBoxIcon.Asterisk);
        return;
      }
    this.Text += this.strDateiName;
    textBox1.SelectionStart = 0;
    textBox1.SelectionLength = 0;
  }
  private void mnuPrintPreview_Click(object sender, EventArgs e) {
    printPreviewDialog1.Document = printDocument1;
    printDialog1.AllowSomePages = true;
    strPrintText = textBox1.Text;
    startSeite = 1;
    anzahlSeiten = printDialog1.PrinterSettings.MaximumPage;
    seitenNummer = 1;
    printPreviewDialog1.ShowDialog();
  }
  private void mnuPageSetup_Click(object sender, EventArgs e) {
    pageSetupDialog1.ShowDialog();
  }
}

Der Ereignishandler von »PrintPage«

Im PrintPage-Ereignishandler befindet sich die gesamte Steuerung des Druckvorgangs. Dazu gehören die Ermittlung der für den Textausdruck zur Verfügung stehenden Rechteckfläche und die Anzahl der Druckzeilen jeder Seite. Dabei darf die letzte Zeile der Seite nicht abgeschnitten werden. Zusätzlich soll jede gedruckte Dokumentenseite eine Kopfzeile mit dem Dateinamen enthalten und in einer Fußzeile die aktuelle Seitezahl anzeigen.

Nach der Deklaration einiger lokaler Variablen, die innerhalb des Ereignishandler benötigt werden, wird mit


rectFPapier = e.MarginBounds;

der Druckbereich des gesamten Ausdrucks festgelegt.

rectFText legt die Größe des Rechtecks fest, in dem der Text aus der Textbox ausgedruckt wird. Die Methode Inflate der Klasse Rectangle vergrößert/verkleinert eine Rechteckfläche. In unserem Fall subtrahieren wir Kopf- und Fußzeile.


rectFText = RectangleF.Inflate(rectFPapier, 
                   0, –2 * textBox1.Font.GetHeight(e.Graphics));

Die Anzahl der Zeilen muss in jedem Fall durch eine gerade Zahl beschrieben werden. Die statische Methode Floor der Klasse Math gibt die größte ganze Zahl zurück, die kleiner oder gleich der angegebenen Zahl ist. Das ist das, was wir benötigen.


int anzahlZeilen = (int)Math.Floor(rectFText.Height / 
                    textBox1.Font.GetHeight(e.Graphics));

Daran schließt sich die Definition des Stringformats an, um den Umbruch des Textes zu beeinflussen.


stringFormat.Trimming = StringTrimming.Word;

Nun sind alle vorbereitenden Initialisierungen beendet, und es kann prinzipiell zur ersten Druckanweisung kommen. Zuvor müssen wir aber noch feststellen, welche Seite als erste ausgedruckt werden soll. Schließlich hat der Anwender die Option, den Ausdruck ab einer beliebigen Seitenzahl zu starten.


while ((seitenNummer < startSeite) && (strPrintText.Length > 0))
{
  e.Graphics.MeasureString(strPrintText, textBox1.Font,
                           rectFText.Size, stringFormat, 
                           out intChars, out intLines);
  strPrintText = strPrintText.Substring(intChars);
  seitenNummer++;
}

Sollte kein Text mehr zum Ausdruck zur Verfügung stehen, muss der Druck beendet werden. In diesem Fall ist die Länge der Variablen strPrintText, die immer den aktuell noch auszudruckenden Text enthält und nach jeder gedruckten Seite aktualisiert wird, gleich null.


if (strPrintText.Length == 0) {
  e.Cancel = true;
  return;
}

Mit


e.Graphics.DrawString(strPrintText, textBox1.Font, 
                      Brushes.Black, rectFText, stringFormat);
strPrintText = strPrintText.Substring(intChars);

wird der Text ausgegeben und der Inhalt der Variablen strPrintText um den ausgedruckten Teil reduziert. Damit sind wir nahezu am Ziel, müssen aber zuerst noch die Kopf- und Fußzeile an den Drucker schicken:


stringFormat.Alignment = StringAlignment.Center;
e.Graphics.DrawString(this.strDateiName,  textBox1.Font, Brushes.Black, 
                      rectFPapier, stringFormat);
stringFormat.LineAlignment = StringAlignment.Far;
e.Graphics.DrawString("Page " + seitenNummer, textBox1.Font, Brushes.Black, 
                      rectFPapier, stringFormat);

Ob eine weitere Seite ausgedruckt werden muss, wird durch die Eigenschaft HasMorePages zum Ausdruck gebracht. Wenn keine weiteren Druckseiten folgen, müssen alle im Ereignishandler benutzten Variablen wieder auf ihren Initialisierungswert zurückgesetzt werden.


e.HasMorePages = (strPrintText.Length > 0) && 
               (seitenNummer < startSeite + anzahlSeiten);
if (!e.HasMorePages)
{
  strPrintText = textBox1.Text;
  startSeite = 1;
  anzahlSeiten = printDialog1.PrinterSettings.MaximumPage;
  seitenNummer = 1;
}

Damit ist das PrintPage-Ereignis fertig implementiert. Der Programmcode sieht vollständig wie folgt aus:


private void printDocument1_PrintPage(object sender, PrintPageEventArgs e) 
{
  StringFormat stringFormat = new StringFormat();
  RectangleF rectFPapier, rectFText;
  int intChars, intLines;
  // Ermitteln des Rectangles, das den gesamten Druckbereich
  // beschreibt (inklusive Kopf- und Fusszeile)
  rectFPapier = e.MarginBounds;
  // Ermitteln des Rectangles, das den Bereich für den
  // Text beschreibt (ausschließlich Kopf- und Fusszeile)
  rectFText = RectangleF.Inflate(rectFPapier, 0, 
                      –2 * textBox1.Font.GetHeight(e.Graphics));
  // eine gerade Anzahl von Druckzeilen ermitteln
  int anzahlZeilen = (int)Math.Floor(rectFText.Height / 
                           textBox1.Font.GetHeight(e.Graphics));
// die Höhe des textbeinhaltenden Rechtecks festlegen, damit die
// letzte Druckzeile nicht abgeschnitten wird
  rectFText.Height = anzahlZeilen * 
                            textBox1.Font.GetHeight(e.Graphics);
  // das StringFormat-Objekt festlegen, um den Text in einem 
  // Rechteck anzuzeigen – Text bis zum nächstliegenden Wort 
  // verkürzen
  stringFormat.Trimming = StringTrimming.Word;
  // legt die Druckstartseite fest, wenn es sich nicht um die
  // erste Dokumentenseite handelt
  while ((seitenNummer < startSeite) && (strPrintText.Length > 0)) {
    e.Graphics.MeasureString(strPrintText, textBox1.Font, 
                         rectFText.Size, stringFormat, 
                         out intChars, out intLines);
    strPrintText = strPrintText.Substring(intChars);
    seitenNummer++;
  }
  // Druckjob beenden, wenn es keinen Text zum Drucken mehr gibt
  if (strPrintText.Length == 0) {
    e.Cancel = true;
    return;
  }
  // den Text an das Graphics-Objekt übergeben
  e.Graphics.DrawString(strPrintText, textBox1.Font, Brushes.Black,                                            rectFText, stringFormat);
  // Text für die nächste Seite
  // intChars – Anzahl der Zeichen in der Zeichenfolge
  // intLines – Anzahl der Zeilen in der Zeichenfolge
  e.Graphics.MeasureString(strPrintText, textBox1.Font,
                           rectFText.Size, stringFormat, 
                           out intChars, out intLines);
  strPrintText = strPrintText.Substring(intChars);
  // StringFormat restaurieren
  stringFormat = new StringFormat();
  // Dateiname in der Kopfzeile anzeigen
  stringFormat.Alignment = StringAlignment.Center;
  e.Graphics.DrawString(this.strDateiName, textBox1.Font,
                        Brushes.Black, rectFPapier, stringFormat);
  // Seitennummer in der Fusszeile anzeigen
  stringFormat.LineAlignment = StringAlignment.Far;
  e.Graphics.DrawString("Page " + seitenNummer, textBox1.Font, 
                       Brushes.Black,rectFPapier, stringFormat);
  // ermitteln, ob weitere Seiten zu drucken sind
  seitenNummer++;
  e.HasMorePages = (strPrintText.Length > 0) && 
                   (seitenNummer < startSeite + anzahlSeiten);
  // Neuinitialisierung
  if (!e.HasMorePages) {
    strPrintText = textBox1.Text;
    startSeite = 1;
    anzahlSeiten = printDialog1.PrinterSettings.MaximumPage;
    seitenNummer = 1;
  }
}

 << zurück
  
  Zum Katalog
Zum Katalog: Visual C# 2005
Visual C# 2005
bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Fortgeschrittene Programmierung mit Visual C# 2005






 Fortgeschrittene
 Programmierung
 mit Visual C# 2005


Zum Katalog: Einstieg in Visual C# 2005






 Einstieg in
 Visual C# 2005


Zum Katalog: Einstieg in Visual Basic 2005






 Einstieg in
 Visual Basic 2005


Zum Katalog: Visual Basic 2005






 Visual Basic 2005


Zum Katalog: Java ist auch eine Insel






 Java ist auch eine
 Insel


Zum Katalog: Konzepte und Lösungen für Microsoft-Netzwerke






 Konzepte und
 Lösungen für
 Microsoft-Netzwerke


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo








Copyright © Galileo Press 2006
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de